package com.earthea.scaffold.common.service;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.earthea.scaffold.common.entity.*;
import com.earthea.scaffold.common.enums.CommonStatusEnum;
import com.earthea.scaffold.common.enums.HttpCodeEnum;
import com.earthea.scaffold.domain.User;
import com.earthea.scaffold.system.service.UserService;
import org.apache.commons.lang3.reflect.MethodUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Optional;

/**
 * 基础服务类
 *
 * @param <ENTITY> 实体对象
 * @param <MAPPER> Mapper对象
 */
public class BaseService<ENTITY extends BaseEntity, MAPPER extends BaseMapper<ENTITY>> extends ServiceImpl<MAPPER, ENTITY> {

    @Autowired
    protected MAPPER mapper;

    @Autowired
    protected UserService userService;

    /**
     * 新增，包装响应体
     *
     * @param entity 实体
     * @return 响应体
     */
    public BaseRsp insert(ENTITY entity) {
        return super.save(entity) ? BaseRsp.success() : BaseRsp.failed();
    }

    /**
     * 按ID修改，包装响应体
     *
     * @param entity 实体
     * @return 响应体
     */
    public BaseRsp modifyById(ENTITY entity) {
        return super.updateById(entity) ? BaseRsp.success() : BaseRsp.failed();
    }

    /**
     * 批量删除，包装响应体
     *
     * @param ids ID列表
     * @return 响应体
     */
    public BaseRsp deleteByIds(List<Long> ids) {
        return super.removeByIds(ids) ? BaseRsp.success() : BaseRsp.failed();
    }

    /**
     * 批量删除，只删除停用状态的数据，包装响应体
     *
     * @param ids ID列表
     * @return 响应体
     */
    public BaseRsp deleteByIdsAndStatus(List<Long> ids) {
        List<ENTITY> entities = mapper.selectByIds(ids);
        int count = 0;
        for (ENTITY entity : entities) {
            Method getStatus = MethodUtils.getAccessibleMethod(entity.getClass(), "getStatus");
            if (getStatus == null) {
                return BaseRsp.failed("entity doesn't have getStatus method");
            }
            try {
                CommonStatusEnum status = (CommonStatusEnum) getStatus.invoke(entity);
                if (CommonStatusEnum.DISABLED.equals(status)) {
                    count += mapper.deleteById(entity);
                }
            } catch (Exception e) {
                log.error("execute getStatus method error", e);
                return BaseRsp.failed("execute getStatus method error");
            }
        }
        return count == 0 ? BaseRsp.failed("normal status cannot delete") : BaseRsp.success();
    }

    /**
     * 删除，包装响应体
     *
     * @param id ID
     * @return 响应体
     */
    public BaseRsp deleteById(Serializable id) {
        return super.removeById(id) ? BaseRsp.success() : BaseRsp.failed();
    }

    /**
     * 按ID查询，包装响应体，创建人更新人翻译
     *
     * @param id ID
     * @return 响应体
     */
    public BaseDataRsp<ENTITY> selectById(Serializable id) {
        ENTITY entity = super.getById(id);
        if (entity != null) {
            if (entity instanceof BaseInsertableEntity insertableEntity) {
                insertableEntity.setCreateUser(Optional.ofNullable(userService.selectCacheById(insertableEntity.getCreateBy())).map(User::getUsername).orElse(null));
            }
            if (entity instanceof BaseUpdatableEntity updatableEntity) {
                updatableEntity.setCreateUser(Optional.ofNullable(userService.selectCacheById(updatableEntity.getCreateBy())).map(User::getUsername).orElse(null));
                updatableEntity.setUpdateUser(Optional.ofNullable(userService.selectCacheById(updatableEntity.getUpdateBy())).map(User::getUsername).orElse(null));
            }
            return new BaseDataRsp<>(entity);
        }
        return new BaseDataRsp<>(HttpCodeEnum.FAIL);
    }

    /**
     * 分页查询，包装响应体，创建人更新人翻译
     *
     * @param req 查询条件，实体是IPage子类
     * @return 响应体
     */
    public PageResult<ENTITY> selectPage(IPage<ENTITY> req) {
        if (mapper instanceof BasePageMapper pageMapper) {
            Page<ENTITY> page = pageMapper.selectPage(req);
            for (ENTITY entity : page.getRecords()) {
                if (entity instanceof BaseInsertableEntity insertableEntity) {
                    insertableEntity.setCreateUser(Optional.ofNullable(userService.selectCacheById(insertableEntity.getCreateBy())).map(User::getUsername).orElse(null));
                }
                if (entity instanceof BaseUpdatableEntity updatableEntity) {
                    updatableEntity.setCreateUser(Optional.ofNullable(userService.selectCacheById(updatableEntity.getCreateBy())).map(User::getUsername).orElse(null));
                    updatableEntity.setUpdateUser(Optional.ofNullable(userService.selectCacheById(updatableEntity.getUpdateBy())).map(User::getUsername).orElse(null));
                }
            }
            return new PageResult<>(page);
        }
        throw new UnsupportedOperationException("mapper doesn't have this method");
    }

}